package com.cskaoyan.market.admin.controller;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;

import com.cskaoyan.market.admin.service.MarketAdminService;
import com.cskaoyan.market.admin.service.impl.MarketAdminServiceImpl;
import com.cskaoyan.market.db.domain.MarketAdmin;
import com.cskaoyan.market.util.AdminResponseCode;
import com.cskaoyan.market.util.JacksonUtil;
import com.cskaoyan.market.util.ResponseUtil;

/**
 * @ClassName AdminAuthController
 * @Description: 总结登录、个人信息、登出接口 /admin/auth/login--post /admin/auth/info---get /admin/auth/logout--post
 * @Author 远志 zhangsong@cskaoyan.onaliyun.com
 * @Date 2023/3/17 10:57
 * @Version V1.0
 **/
@WebServlet("/admin/auth/*")
public class AdminAuthController extends HttpServlet {

    private MarketAdminService adminService = new MarketAdminServiceImpl();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String requestURI = req.getRequestURI();
        String op = requestURI.replace(req.getContextPath() + "/admin/auth/", "");
        if ("info".equals(op)) {
            info(req, resp);
        }
    }

    private void info(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        HttpSession session = req.getSession();
        MarketAdmin admin = (MarketAdmin)session.getAttribute("info");
        Map<Object, Object> result = new HashMap<>();
        result.put("roles", Arrays.asList(new String[] {"超级管理员"}));
        result.put("name", admin.getUsername());
        result.put("perms", Arrays.asList(new String[] {"*"}));
        result.put("avatar", admin.getAvatar());
        Object data = ResponseUtil.ok(result);
        resp.getWriter().println(JacksonUtil.writeValueAsString(data));
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String requestURI = req.getRequestURI();
        String op = requestURI.replace(req.getContextPath() + "/admin/auth/", "");
        if ("login".equals(op)) {
            login(req, resp);
        } else if ("logout".equals(op)) {
            logout(req, resp);
        }

    }

    private void logout(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        req.getSession().invalidate();
        resp.getWriter().println(JacksonUtil.writeValueAsString(ResponseUtil.ok()));
    }

    private void login(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 1.首先解析位于请求体中的json字符串
        // 因为客户端发往当前地址提交的是文本类型的数据，所以我们直接将其解析成字符串
        ServletInputStream inputStream = req.getInputStream();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        int length = 0;
        byte[] bytes = new byte[1024];
        while ((length = inputStream.read(bytes)) != -1) {
            outputStream.write(bytes, 0, length);
        }
        // {"username":"admin123","password":"admin123"}
        String requestBody = outputStream.toString("utf-8");
        outputStream.close();

        // 2.获取json字符串中的用户名、密码参数信息。进行常规的校验、判空处理
        // 获取用户名、密码等信息，可以有两种方式 1.新建一个新的类，利用json解析工具将json字符串转换成java对象，再从java对象中获取属性值 2.利用JsonNode类，利用键值对来读取
        // 如何选择？如果属性比较少，那么建议使用方式2；如果对象非常复杂，存在对象包含对象的情形，建议选择1
        String username = JacksonUtil.parseString(requestBody, "username");
        String password = JacksonUtil.parseString(requestBody, "password");
        // 校验 TODO
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            // 这是一个map，你需要将其转换成json字符串，写入到响应体中
            // 接下来我们需要返回的结果
            Object o = ResponseUtil.badArgument();
            // 转换成json字符串
            String jsonStr = JacksonUtil.writeValueAsString(o);
            // json字符串写入到响应体
            resp.getWriter().println(jsonStr);
            return;
        }
        //
        // 3.调用业务层代码，进行登录校验，校验用户名、密码是否正确；如果不匹配直接返回结果
        MarketAdmin admin = adminService.login(username, password);
        if (admin == null) {
            // 没有查找到数据，登录失败，用户名、密码错误
            // 如何返回暂时还不知道 TODO response.getWriter().println(""登录失败)不能再这么写了
            resp.getWriter().println(JacksonUtil
                .writeValueAsString(ResponseUtil.fail(AdminResponseCode.ADMIN_INVALID_PASSWORD, "用户名、密码错误")));
            return;
        }
        // 修改表----修改最近登录的ip地址、最新的访问时间
        // 4.如果校验通过，则需要修改一次market_admin表，需要更新最新的登录ip地址、登录时间
        String remoteAddr = req.getRemoteAddr();
        admin.setLastLoginIp(remoteAddr);
        admin.setLastLoginTime(LocalDateTime.now());
        adminService.updateById(admin);
        Map<String, Object> result = new HashMap<>();
        Map<String, Object> adminInfo = new HashMap<>();
        adminInfo.put("nickName", admin.getUsername());
        adminInfo.put("avatar", admin.getAvatar());
        result.put("adminInfo", adminInfo);
        // token这里面就是session的编号
        HttpSession session = req.getSession();
        session.setAttribute("info", admin);
        String id = session.getId();
        result.put("token", id);
        resp.getWriter().println(JacksonUtil.writeValueAsString(ResponseUtil.ok(result)));
        //
        //
        // 5.返回结果（需要抓取公网的返回值，做到返回值相同即可）
    }
}